
namespace Patterns4Net.ArchitectureExplorer.ViewModels.Graph
{
    using Diagram.Relations;
    using Attributes;
    using System.Diagnostics.Contracts;
    using Graphviz4Net.Graphs;
    using Diagram;
    using Attributes.DesignPatterns;

    /// <summary>
    /// Adapts an instance of <see cref="Relation"/> to Graphviz4Net edge representation.
    /// </summary>
    /// <typeparam name="TViewModel">The type of the view model.</typeparam>
    [Adapter(Adaptee=typeof(Relation), Target=typeof(Edge<>))]
    [PatternEnforcerIgnore(Justification = "Pattern Enforcer does not support generics yet.")]
    public class RelationViewModel<TViewModel> : Edge<TViewModel>
    {
        public RelationViewModel(
            TViewModel source,
            TViewModel target,
            Relation relation)
            : base(source, target)
        {
            Contract.Requires(source != null);
            Contract.Requires(target != null);
            Contract.Requires(relation != null);

            this.Label = relation.Name;
            this.Relation = relation;
            this.SetUpArrowLabels();

            this.Attributes["minlen"] = "1.75";
            if (relation is Uses)
            {                
                this.Attributes["constraint"] = "false";
            }
        }

        /// <summary>
        /// Gets or the original adapted relation.
        /// </summary>
        public Relation Relation { get; private set; }

        /// <summary>
        /// Gets the objects that represents the arrow from target to source.
        /// </summary>
        public override object SourceArrow
        {
            get
            {
                if (this.Relation.IsBidirectional == false)
                {
                    return null;
                }

                return this.Relation.SourceArrow;
            }
        }

        /// <summary>
        /// Gets the objects that represents the arrow from source to target.
        /// </summary>
        public override object DestinationArrow
        {
            get { return this.Relation.TargetArrow; }
        }

        /// <summary>
        /// This is used in xaml for selection of graphical style of the line.
        /// </summary>
        public string RelationName
        {
            get { return this.Relation.GetType().Name; }
        }

        private void SetUpArrowLabels()
        {
            this.DestinationArrowLabel = this.Relation.TargetCardinalityString;
            if (this.Relation.IsBidirectional)
            {
                this.SourceArrowLabel = this.Relation.SourceCardinalityString;
            }
        }
    }
}
